/* 好友申请事件表的ODB映射操作 */

#include "mysql.hpp"
#include "friend_apply.hxx"
#include "friend_apply-odb.hxx"


namespace ChatSystem
{
    //好友申请事件表ODB操作
    class FriendApplyTable
    {
    public:
        using ptr = std::shared_ptr<FriendApplyTable>;

        FriendApplyTable() = delete;
        FriendApplyTable(const std::shared_ptr<odb::core::database>& db)
        :_db(db)
        {}
        ~FriendApplyTable(){}

        //新增好友申请事件
        bool insert(ChatSystem::FriendApply& friend_apply_event)
        {
            //数据的所有操作都会有可能导致程序的崩溃，所以需要捕捉异常防止程序的退出；
            try
            {
                //获取对象开启事务
                odb::transaction trans(_db->begin());
                _db->persist(friend_apply_event);
                //提交事务
                trans.commit();
            }
            catch(const std::exception& e)
            {
                LOG_ERROR("在好友申请事件表中新增好友申请事件 {}: {}->{} 时失败, {}!", friend_apply_event.event_id(), 
                    friend_apply_event.user_id(), friend_apply_event.peer_id(), e.what());
                return false;
            }
            return true;   
        }

        //删除好友申请事件---通过好友申请事件的事件ID来删除数据
        bool remove(const std::string& event_id)
        {
            //数据的所有操作都会有可能导致程序的崩溃，所以需要捕捉异常防止程序的退出；
            try
            {
                //获取对象开启事务
                odb::transaction trans(_db->begin());
                //1. 先查询
                typedef odb::query<FriendApply> query;
                typedef odb::result<FriendApply> result;
                _db->erase_query<FriendApply>(query::event_id == event_id);
                //提交事务
                trans.commit();
            }
            catch(const std::exception& e)
            {
                LOG_ERROR("通过好友申请事件ID {} 删除好友申请事件时失败, {}!", event_id, e.what());
                return false;
            }
            return true;  
        }
        //删除好友申请事件---通过好友申请事件中对应的用户ID和好友ID来删除数据
        bool remove(const std::string& user_id, const std::string& peer_id)
        {
            //数据的所有操作都会有可能导致程序的崩溃，所以需要捕捉异常防止程序的退出；
            try
            {
                //获取对象开启事务
                odb::transaction trans(_db->begin());
                //1. 先查询
                typedef odb::query<FriendApply> query;
                typedef odb::result<FriendApply> result;
                _db->erase_query<FriendApply>(query::user_id == user_id && query::peer_id == peer_id);
                //提交事务
                trans.commit();
            }
            catch(const std::exception& e)
            {
                LOG_ERROR("通过用户ID和好友ID来删除好友申请 {}->{} 事件时失败, {}!", user_id, peer_id, e.what());
                return false;
            }
            return true;  
        }

        //判断是否已经存在好友申请事件了
        bool exists(const std::string& user_id, const std::string& peer_id)
        {
            bool flag = false;
            //数据的所有操作都会有可能导致程序的崩溃，所以需要捕捉异常防止程序的退出；
            try
            {
                //获取对象开启事务
                odb::transaction trans(_db->begin());
                //1. 先查询
                typedef odb::query<FriendApply> query;
                typedef odb::result<FriendApply> result;
                result r(_db->query<FriendApply>(query::user_id == user_id && query::peer_id == peer_id));
                flag = !r.empty();
                //提交事务
                trans.commit();
            }
            catch(const std::exception& e)
            {
                LOG_ERROR("通过用户ID和好友ID来判断申请好友 {}->{} 事件是否存在时失败, {}!", user_id, peer_id, e.what());
                return false;
            }
            return flag; 
        }

        //获取指定用户的所有好友申请者
        std::vector<std::string> applyUsers(const std::string& user_id)
        {
            std::vector<std::string> res;
            //数据的所有操作都会有可能导致程序的崩溃，所以需要捕捉异常防止程序的退出；
            try
            {
                //3. 获取事务操作对象，开启事务
                odb::transaction trans(_db->begin());
                //4. 数据操作
                typedef odb::query<FriendApply> query;
                typedef odb::result<FriendApply> result;
                //注意：当前的uid是被申请者的用户ID，是要查看是哪些人申请了自己
                result r(_db->query<FriendApply>(query::peer_id == user_id));
                for(auto it = r.begin(); it != r.end(); ++it)
                {
                    res.push_back(it->user_id());
                }
                //5. 提交事务
                trans.commit();
            }
            catch(std::exception& e)
            {
                LOG_ERROR("获取用户 {} 的所有好友申请者时失败, {}", user_id, e.what());
            }
            return res;
        }
    
    private:
        std::shared_ptr<odb::core::database> _db;
    };
}